Merge pull request #47 from albertsun/twitter_publish_agent

TwitterPublishAgent

Andrew Cantino 11 years ago
parent
commit
d4a45dc71f
2 changed files with 142 additions and 0 deletions
  1. 86 0
      app/models/agents/twitter_publish_agent.rb
  2. 56 0
      spec/models/agents/twitter_publish_agent_spec.rb

+ 86 - 0
app/models/agents/twitter_publish_agent.rb

@@ -0,0 +1,86 @@
1
+require "twitter"
2
+
3
+module Agents
4
+  class TwitterPublishAgent < Agent
5
+    cannot_be_scheduled!
6
+
7
+    description <<-MD
8
+      The TwitterPublishAgent publishes tweets from the events it receives.
9
+
10
+      You must set up a Twitter app and provide it's `consumer_key`, `consumer_secret`, `oauth_token` and `oauth_token_secret`,
11
+      (Also shown as "Access token" on the Twitter developer's site.) along with the `username` of the Twitter user to publish as.
12
+
13
+      The `oauth_token` and `oauth_token_secret` specified determine which user the tweet will be sent as.
14
+
15
+      You must also specify a `message_path` parameter: a [JSONPaths](http://goessner.net/articles/JsonPath/) to the value to tweet.
16
+
17
+      Set `expected_update_period_in_days` to the maximum amount of time that you'd expect to pass between Events being created by this Agent.
18
+    MD
19
+
20
+    def validate_options
21
+      unless options[:username].present? &&
22
+        options[:expected_update_period_in_days].present? &&
23
+        options[:consumer_key].present? &&
24
+        options[:consumer_secret].present? &&
25
+        options[:oauth_token].present? &&
26
+        options[:oauth_token_secret].present?
27
+        errors.add(:base, "expected_update_period_in_days, username, consumer_key, consumer_secret, oauth_token and oauth_token_secret are required")
28
+      end
29
+    end
30
+
31
+    def working?
32
+      (event = event_created_within(options[:expected_update_period_in_days].to_i.days)) && event.payload.present? && event.payload[:success] == true
33
+    end
34
+
35
+    def default_options
36
+      {
37
+          :username => "",
38
+          :expected_update_period_in_days => "10",
39
+          :consumer_key => "---",
40
+          :consumer_secret => "---",
41
+          :oauth_token => "---",
42
+          :oauth_token_secret => "---",
43
+          :message_path => "text"
44
+      }
45
+    end
46
+
47
+    def receive(incoming_events)
48
+      # if there are too many, dump a bunch to avoid getting rate limited
49
+      if incoming_events.count > 20
50
+        incoming_events = incoming_events.first(20)
51
+      end
52
+      incoming_events.each do |event|
53
+        tweet_text = Utils.value_at(event.payload, options[:message_path])
54
+        begin
55
+          publish_tweet tweet_text
56
+          create_event :payload => {
57
+            :success => true,
58
+            :published_tweet => tweet_text,
59
+            :agent_id => event.agent_id,
60
+            :event_id => event.id
61
+          }
62
+        rescue Twitter::Error => e
63
+          create_event :payload => {
64
+            :success => false,
65
+            :error => e.message,
66
+            :failed_tweet => tweet_text,
67
+            :agent_id => event.agent_id,
68
+            :event_id => event.id
69
+          }
70
+        end
71
+      end
72
+    end
73
+
74
+    def publish_tweet text
75
+      Twitter.configure do |config|
76
+        config.consumer_key = options[:consumer_key]
77
+        config.consumer_secret = options[:consumer_secret]
78
+        config.oauth_token = options[:oauth_token]
79
+        config.oauth_token_secret = options[:oauth_token_secret]
80
+      end
81
+
82
+      Twitter.update(text)
83
+    end
84
+
85
+  end
86
+end

+ 56 - 0
spec/models/agents/twitter_publish_agent_spec.rb

@@ -0,0 +1,56 @@
1
+require 'spec_helper'
2
+
3
+describe Agents::TwitterPublishAgent do
4
+  before do
5
+    @opts = {
6
+      :username => "HuginnBot",
7
+      :expected_update_period_in_days => "2",
8
+      :consumer_key => "---",
9
+      :consumer_secret => "---",
10
+      :oauth_token => "---",
11
+      :oauth_token_secret => "---",
12
+      :message_path => "text"
13
+    }
14
+
15
+    @checker = Agents::TwitterPublishAgent.new(:name => "HuginnBot", :options => @opts)
16
+    @checker.user = users(:bob)
17
+    @checker.save!
18
+
19
+    @event = Event.new
20
+    @event.agent = agents(:bob_weather_agent)
21
+    @event.payload = { :text => 'Gonna rain..' }
22
+    @event.save!
23
+
24
+    @sent_messages = []
25
+    stub.any_instance_of(Agents::TwitterPublishAgent).publish_tweet { |message| @sent_messages << message}
26
+  end
27
+
28
+  describe '#receive' do
29
+    it 'should publish any payload it receives' do
30
+      event1 = Event.new
31
+      event1.agent = agents(:bob_rain_notifier_agent)
32
+      event1.payload = { :text => 'Gonna rain..' }
33
+      event1.save!
34
+
35
+      event2 = Event.new
36
+      event2.agent = agents(:bob_weather_agent)
37
+      event2.payload = { :text => 'More payload' }
38
+      event2.save!
39
+
40
+      Agents::TwitterPublishAgent.async_receive(@checker.id, [event1.id, event2.id])
41
+      @sent_messages.count.should eq(2)
42
+      @checker.events.count.should eq(2)
43
+    end
44
+  end
45
+
46
+  describe '#working?' do
47
+    it 'checks if events have been received within the expected receive period' do
48
+      @checker.should_not be_working # No events received
49
+      Agents::TwitterPublishAgent.async_receive(@checker.id, [@event.id])
50
+      @checker.reload.should be_working # Just received events
51
+      two_days_from_now = 2.days.from_now
52
+      stub(Time).now { two_days_from_now }
53
+      @checker.reload.should_not be_working # More time has passed than the expected receive period without any new events
54
+    end
55
+  end
56
+end